package com.xingkeduo.service.api.activity.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xingkeduo.dao.TActivityDaysMapper;
import com.xingkeduo.dao.TActivityMapper;
import com.xingkeduo.dao.TMarketingReceiveHistoryCardMapper;
import com.xingkeduo.dao.TMarketingReceiveHistoryCouponBagMapper;
import com.xingkeduo.dao.TMarketingReceiveHistoryCouponMapper;
import com.xingkeduo.feign.HairstyleFeignService;
import com.xingkeduo.feign.ManageUserFeignService;
import com.xingkeduo.feign.OrderFeignService;
import com.xingkeduo.model.example.TMarketingReceiveHistoryCardExample;
import com.xingkeduo.model.example.TMarketingReceiveHistoryCouponExample;
import com.xingkeduo.model.param.ActivityCombinationParam;
import com.xingkeduo.model.param.ActivityParam.ActivityTypeEnum;
import com.xingkeduo.model.param.ActivityParam.PreferentialModeEnum;
import com.xingkeduo.model.param.ActivityUseParam;
import com.xingkeduo.model.param.MarketingParam.MarketingServiceTypeEnum;
import com.xingkeduo.model.param.MarketingParam.MarketingTypeEnum;
import com.xingkeduo.model.po.TActivity;
import com.xingkeduo.model.po.TMarketingReceiveHistory;
import com.xingkeduo.model.vo.MarketingReceiveHistoryResponseVo;
import com.xingkeduo.model.vo.UserActivityResponseVo;
import com.xingkeduo.model.vo.api.ActivityApiResponseVo;
import com.xingkeduo.model.vo.base.ActivityCalculation;
import com.xingkeduo.model.vo.base.BaseActivityResponse;
import com.xingkeduo.service.api.activity.PreferentialActivityService;
import com.xingkeduo.service.api.activity.UserActivityService;
import com.xingkeduo.service.consume.UserService;
import com.xingkeduo.util.Constant;
import com.xingkeduo.util.DateUtils;
import com.xingkeduo.util.tool.ResponseMessage;

@Service
public class PreferentialActivityServiceImpl implements PreferentialActivityService {
	Logger logger = LoggerFactory.getLogger(PreferentialActivityServiceImpl.class);
	@Autowired
	TActivityDaysMapper tActivityDaysMapper;
	@Autowired
	HairstyleFeignService hairstyleFeignService;
	@Autowired
	TActivityMapper tActivityMapper;
	@Autowired
	UserActivityService userActivityService;
	@Autowired
	ManageUserFeignService manageUserFeignService;
	@Autowired
	OrderFeignService orderFeignService;
	@Autowired
	TMarketingReceiveHistoryCardMapper tMarketingReceiveHistoryCardMapper;
	@Autowired
	TMarketingReceiveHistoryCouponMapper tMarketingReceiveHistoryCouponMapper;
	@Autowired
	TMarketingReceiveHistoryCouponBagMapper tMarketingReceiveHistoryCouponBagMapper;
	@Autowired
	UserService userService;

	@SuppressWarnings("unused")
	@Override
	public ResponseMessage getRecommendedPackage(ActivityCombinationParam param) {
		// 查询用户所有权益-含用户所有可用券，卡，及当前门店活动
		UserActivityResponseVo response = getUserAllAvailableActivity(param);
		logger.info("【最优活动】门店设置最优活动，activityCombinationParam2:{}",JSON.toJSONString(param));
		// 不叠加的活动和卡，券
		ActivityCalculation onlyActivityChoiceData = new ActivityCalculation();
		// 1 对互斥数据筛选，挑选出互斥情况下活动和券，卡的最大优惠数据
		// 1.1取出互斥数据中，门店活动最大优惠数据-并返回可叠加使用的活动
		List<BaseActivityResponse> newAvailableActivityList = getExcludeOnlyChoiceActivity(param,
				onlyActivityChoiceData, response.getAvailableActivityList());
		// 门店设置了类似0元剪发的服务，直接返回
		if (onlyActivityChoiceData.getActivityId() != null
				&& onlyActivityChoiceData.getActivityReduceAmount().compareTo(param.getHairServiceOriginPrice()) >= 0) {
			logger.info("【最优活动】门店设置最优活动，onlyActivityChoiceData:{}",JSON.toJSONString(onlyActivityChoiceData));
			return ResponseMessage.ok(onlyActivityChoiceData);
		}
		// 若没有门店活动，则所有的券，卡都可以按照互斥处理的。
		Boolean isExcludeOnylyMarketing = false;
		if (CollectionUtils.isEmpty(newAvailableActivityList)) {
			isExcludeOnylyMarketing = true;
		}
		ActivityCalculation onlyMarketingChoiceData = new ActivityCalculation();
		// 1.2取出互斥数据中，券最大优惠数据-并返回可叠加使用的券
		List<BaseActivityResponse> newAvailableCouponList = getExcludeOnlyChoiceMarketing(param,
				onlyMarketingChoiceData, 1, isExcludeOnylyMarketing, response.getAvailableCouponList());
		// 1.3取出互斥数据中，卡最大优惠数据-并返回可叠加使用的卡
		List<BaseActivityResponse> newAvailableCardList = getExcludeOnlyChoiceMarketing(param, onlyMarketingChoiceData,
				2, isExcludeOnylyMarketing, response.getAvailableCardList());
		// 用户有类似0元剪发的券，卡，直接返回
		if (onlyMarketingChoiceData.getMarketingId() != null && onlyMarketingChoiceData.getMarketingReduceAmount()
				.compareTo(param.getHairServiceOriginPrice()) >= 0) {
			logger.info("【最优活动】用户有免费券卡，onlyActivityChoiceData:{}",JSON.toJSONString(onlyActivityChoiceData));
			return ResponseMessage.ok(onlyMarketingChoiceData);
		}
		// 2 叠加情况下的券，卡和活动
		ActivityCalculation combinationData = screenActivityAndMarketingCombinationData(param, newAvailableActivityList,
				newAvailableCouponList, newAvailableCardList);
		// 分别获取最大优惠额度
		BigDecimal onlyActivityReduceAmount = BigDecimal.valueOf(0);
		BigDecimal onlyMarketingReduceAmount = BigDecimal.valueOf(0);
		BigDecimal combinationReduceAmount = BigDecimal.valueOf(0);
		if (onlyActivityChoiceData.getActivityId() != null) {
			onlyActivityReduceAmount = onlyActivityChoiceData.getActivityReduceAmount() == null ? BigDecimal.valueOf(0)
					: onlyActivityChoiceData.getActivityReduceAmount();
		}
		if (onlyMarketingChoiceData.getMarketingId() != null) {
			onlyMarketingReduceAmount = onlyMarketingChoiceData.getMarketingReduceAmount() == null
					? BigDecimal.valueOf(0)
					: onlyMarketingChoiceData.getMarketingReduceAmount();
		}
		if (combinationData != null) {
			BigDecimal activityReduceAmount = combinationData.getActivityReduceAmount() == null ? BigDecimal.valueOf(0)
					: combinationData.getActivityReduceAmount();
			BigDecimal marketingReduceAmount = combinationData.getMarketingReduceAmount() == null
					? BigDecimal.valueOf(0)
					: combinationData.getMarketingReduceAmount();
			combinationReduceAmount = activityReduceAmount.add(marketingReduceAmount).setScale(2,
					BigDecimal.ROUND_HALF_UP);
		}
		if (onlyActivityReduceAmount.compareTo(onlyMarketingReduceAmount) >= 0) {
			if (onlyActivityReduceAmount.compareTo(combinationReduceAmount) >= 0) {
				return ResponseMessage.ok(onlyActivityChoiceData);
			} else {
				return ResponseMessage.ok(combinationData);
			}
		} else {
			if (onlyMarketingReduceAmount.compareTo(combinationReduceAmount) >= 0) {
				return ResponseMessage.ok(onlyMarketingChoiceData);
			} else {
				return ResponseMessage.ok(combinationData);
			}
		}
	}

	private ActivityCalculation screenActivityAndMarketingCombinationData(ActivityCombinationParam param,
			List<BaseActivityResponse> newAvailableActivityList, List<BaseActivityResponse> newAvailableCouponList,
			List<BaseActivityResponse> newAvailableCardList) {
		ActivityCalculation combinationData = null;
		for (BaseActivityResponse activityResponse : newAvailableActivityList) {
			ActivityApiResponseVo activity = (ActivityApiResponseVo) activityResponse;
			BigDecimal activityReduceAmount = BigDecimal.valueOf(0);
			Integer activityDiscountType = 0;
			if (activity.getPreferentialMode() == PreferentialModeEnum.REDUCE.getCode()) {
				activityReduceAmount = activity.getActivityAmount();
				activityDiscountType = PreferentialModeEnum.REDUCE.getCode();
			}
			if (activity.getPreferentialMode() == PreferentialModeEnum.DISCOUNT.getCode()) {
				activityReduceAmount = param.getHairServiceOriginPrice()
						.multiply(BigDecimal.valueOf(1).subtract(activity.getActivityAmount()))
						.setScale(2, BigDecimal.ROUND_HALF_UP);
				activityDiscountType = PreferentialModeEnum.DISCOUNT.getCode();
			}
			if (activity.getPreferentialMode() == PreferentialModeEnum.SPECIAL_OFFER.getCode()) {
				activityReduceAmount = param.getHairServiceOriginPrice().subtract(activity.getActivityAmount())
						.setScale(2, BigDecimal.ROUND_HALF_UP);
				activityReduceAmount = activityReduceAmount.compareTo(BigDecimal.valueOf(0)) < 0 ? BigDecimal.valueOf(0) : activityReduceAmount;
				activityDiscountType = PreferentialModeEnum.SPECIAL_OFFER.getCode();
			}
			if (activity.getPreferentialMode() == PreferentialModeEnum.FREE.getCode()) {
				activityReduceAmount = param.getHairServiceOriginPrice().setScale(2, BigDecimal.ROUND_HALF_UP);
				activityDiscountType = PreferentialModeEnum.FREE.getCode();
			}
			activityReduceAmount = activityReduceAmount.compareTo(param.getHairServiceOriginPrice()) > 0 ? param.getHairServiceOriginPrice() : activityReduceAmount;
			if (combinationData != null
					&& combinationData.getActivityReduceAmount().compareTo(activityReduceAmount) > 0) {
				continue;
			}
			if (combinationData != null
					&& combinationData.getActivityReduceAmount().compareTo(activityReduceAmount) == 0
					&& combinationData.getActivityEndTime().after(activity.getEndTime())
					&& !combinationData.getIsBypassFlow()) {
				combinationData.setActivityId(activity.getId());
				combinationData.setActivityDiscountType(activityDiscountType);
				combinationData.setActivityType(0);
				combinationData.setActivityReduceAmount(activityReduceAmount);
				combinationData.setActivityDenominationAmount(activity.getActivityAmount());
				combinationData.setActivityName(activity.getName());
				combinationData.setActivityEndTime(activity.getEndTime());
				continue;
			}
			if (combinationData == null) {
				combinationData = new ActivityCalculation(activity.getId(), activityReduceAmount, activityDiscountType,
						activity.getActivityAmount(), activity.getName(), 0, activity.getEndTime(),activity.getActivityType().equalsIgnoreCase(ActivityTypeEnum.BYPASS_FLOW.getStatusType()));
			}
			BigDecimal price = param.getHairServiceOriginPrice().subtract(activityReduceAmount).setScale(2,
					BigDecimal.ROUND_HALF_UP);
			// 券筛选
			screenCouponData(newAvailableCouponList, combinationData, activity, activityReduceAmount,
					activityDiscountType, price);
			// 卡筛选
			screenCardData(newAvailableCardList, combinationData, activity, activityReduceAmount, activityDiscountType,
					price);
		}
		return combinationData;
	}

	private void screenCardData(List<BaseActivityResponse> newAvailableCardList, ActivityCalculation combinationData,
			ActivityApiResponseVo activity, BigDecimal activityReduceAmount, Integer activityDiscountType,
			BigDecimal price) {
		for (BaseActivityResponse marketingResponse : newAvailableCardList) {
			MarketingReceiveHistoryResponseVo marketing = (MarketingReceiveHistoryResponseVo) marketingResponse;
			BigDecimal marketingReduceAmount = BigDecimal.valueOf(0);
			Integer marketingDiscountType = 0;
			if (marketing.getServiceType().equals(MarketingServiceTypeEnum.DISCOUNT.getType())) {
				marketingReduceAmount = price.multiply(BigDecimal.valueOf(1).subtract(marketing.getCouponAmount()))
						.setScale(2, BigDecimal.ROUND_HALF_UP);
				marketingDiscountType = PreferentialModeEnum.DISCOUNT.getCode();
			}
			if (marketing.getServiceType().equals(MarketingServiceTypeEnum.CASH.getType())) {
				marketingReduceAmount = marketing.getCouponAmount().setScale(2, BigDecimal.ROUND_HALF_UP);
				marketingDiscountType = PreferentialModeEnum.REDUCE.getCode();
			}
			marketingReduceAmount = marketingReduceAmount.compareTo(price) > 0 ? price : marketingReduceAmount;
			if (combinationData.getMarketingId() == null) {
				combinationData.setMarketingId(marketing.getId());
				combinationData.setMarketingType(2);
				combinationData.setMarketingReduceAmount(marketingReduceAmount);
				combinationData.setMarketingDiscountType(marketingDiscountType);
				combinationData.setMarketingDenominationAmount(marketing.getCouponAmount());
				combinationData.setMarketingName(marketing.getMarketingName());
				combinationData.setMarketingEndTime(marketing.getUseEndTime());
				combinationData.setMarketingRefundType(marketing.getRefundType());
				combinationData.setMarketingSubsidyType(marketing.getPreferentialUndertakeType());
				combinationData.setMarketingSubsidyBasicAmount(marketing.getHeadquartersPreferentialUndertake());
				continue;
			}
			BigDecimal totalReduceAmount = marketingReduceAmount.add(activityReduceAmount).setScale(2,
					BigDecimal.ROUND_HALF_UP);
			if ((combinationData.getMarketingReduceAmount().add(combinationData.getActivityReduceAmount()))
					.compareTo(totalReduceAmount) < 0
					|| ((combinationData.getMarketingReduceAmount().add(combinationData.getActivityReduceAmount()))
							.compareTo(totalReduceAmount) == 0
							&& marketing.getUseEndTime().before(combinationData.getMarketingEndTime()))) {
				combinationData.setMarketingId(marketing.getId());
				combinationData.setMarketingType(2);
				combinationData.setMarketingReduceAmount(marketingReduceAmount);
				combinationData.setMarketingDiscountType(marketingDiscountType);
				combinationData.setMarketingDenominationAmount(marketing.getCouponAmount());
				combinationData.setMarketingName(marketing.getMarketingName());
				combinationData.setMarketingEndTime(marketing.getUseEndTime());
				combinationData.setMarketingRefundType(marketing.getRefundType());
				combinationData.setMarketingSubsidyType(marketing.getPreferentialUndertakeType());
				combinationData.setMarketingSubsidyBasicAmount(marketing.getHeadquartersPreferentialUndertake());
			}
		}
	}

	private void screenCouponData(List<BaseActivityResponse> newAvailableCouponList,
			ActivityCalculation combinationData, ActivityApiResponseVo activity, BigDecimal activityReduceAmount,
			Integer activityDiscountType, BigDecimal price) {
		for (BaseActivityResponse marketingResponse : newAvailableCouponList) {
			MarketingReceiveHistoryResponseVo marketing = (MarketingReceiveHistoryResponseVo) marketingResponse;
			BigDecimal marketingReduceAmount = BigDecimal.valueOf(0);
			Integer marketingDiscountType = 0;
			if (marketing.getServiceType().equals(MarketingServiceTypeEnum.DISCOUNT.getType())) {
				marketingReduceAmount = price.multiply(BigDecimal.valueOf(1).subtract(marketing.getCouponAmount()))
						.setScale(2, BigDecimal.ROUND_HALF_UP);
				marketingDiscountType = PreferentialModeEnum.DISCOUNT.getCode();
			}
			if (marketing.getServiceType().equals(MarketingServiceTypeEnum.CASH.getType())) {
				marketingReduceAmount = marketing.getCouponAmount().setScale(2, BigDecimal.ROUND_HALF_UP);
				marketingDiscountType = PreferentialModeEnum.REDUCE.getCode();
			}
			marketingReduceAmount = marketingReduceAmount.compareTo(price) > 0 ? price : marketingReduceAmount;
			if (combinationData.getMarketingId() == null) {
				combinationData.setMarketingId(marketing.getId());
				combinationData.setMarketingType(1);
				combinationData.setMarketingReduceAmount(marketingReduceAmount);
				combinationData.setMarketingDiscountType(marketingDiscountType);
				combinationData.setMarketingDenominationAmount(marketing.getCouponAmount());
				combinationData.setMarketingName(marketing.getMarketingName());
				combinationData.setMarketingEndTime(marketing.getUseEndTime());
				combinationData.setMarketingRefundType(marketing.getRefundType());
				combinationData.setMarketingSubsidyType(marketing.getPreferentialUndertakeType());
				combinationData.setMarketingSubsidyBasicAmount(marketing.getHeadquartersPreferentialUndertake());
				continue;
			}

			BigDecimal totalReduceAmount = marketingReduceAmount.add(activityReduceAmount).setScale(2,
					BigDecimal.ROUND_HALF_UP);
			if ((combinationData.getMarketingReduceAmount().add(combinationData.getActivityReduceAmount()))
					.compareTo(totalReduceAmount) < 0
					|| ((combinationData.getMarketingReduceAmount().add(combinationData.getActivityReduceAmount()))
							.compareTo(totalReduceAmount) == 0
							&& marketing.getUseEndTime().before(combinationData.getMarketingEndTime()))) {
				combinationData.setMarketingId(marketing.getId());
				combinationData.setMarketingType(1);
				combinationData.setMarketingReduceAmount(marketingReduceAmount);
				combinationData.setMarketingDiscountType(marketingDiscountType);
				combinationData.setMarketingDenominationAmount(marketing.getCouponAmount());
				combinationData.setMarketingName(marketing.getMarketingName());
				combinationData.setMarketingEndTime(marketing.getUseEndTime());
				combinationData.setMarketingRefundType(marketing.getRefundType());
				combinationData.setMarketingSubsidyType(marketing.getPreferentialUndertakeType());
				combinationData.setMarketingSubsidyBasicAmount(marketing.getHeadquartersPreferentialUndertake());
			}
		}
	}

	private UserActivityResponseVo getUserAllAvailableActivity(ActivityCombinationParam param) {
		buildUserAllUserIds(param);
		UserActivityResponseVo response = new UserActivityResponseVo();
		userActivityService.getUserAvailableStoreActivity(param, response);
		userActivityService.getUserAvailableCouponActivity(param, response);
		userActivityService.getUserAvailableCardActivity(param, response);
		return response;
	}

	private List<BaseActivityResponse> getExcludeOnlyChoiceMarketing(ActivityCombinationParam param,
			ActivityCalculation data, Integer activityType, Boolean isExcludeOnylyMarketing,
			List<BaseActivityResponse> availableCouponList) {
		List<BaseActivityResponse> responseList = new ArrayList<BaseActivityResponse>();
		for (BaseActivityResponse marketingResponse : availableCouponList) {
			MarketingReceiveHistoryResponseVo marketing = (MarketingReceiveHistoryResponseVo) marketingResponse;
			BigDecimal reduceAmount = BigDecimal.valueOf(0);
			Integer actType = 0;
			if (marketing.getServiceType().equals(MarketingServiceTypeEnum.DISCOUNT.getType())) {
				reduceAmount = param.getHairServiceOriginPrice()
						.multiply(BigDecimal.valueOf(1).subtract(marketing.getCouponAmount()))
						.setScale(2, BigDecimal.ROUND_HALF_UP);
				actType = PreferentialModeEnum.DISCOUNT.getCode();
			}
			if (marketing.getServiceType().equals(MarketingServiceTypeEnum.CASH.getType())) {
				reduceAmount = marketing.getCouponAmount();
				actType = PreferentialModeEnum.REDUCE.getCode();
			}
			if (marketing.getServiceType().equals(MarketingServiceTypeEnum.FIXED.getType())) {
				reduceAmount = param.getHairServiceOriginPrice().subtract(marketing.getCouponAmount()).setScale(2,
						BigDecimal.ROUND_HALF_UP);
				reduceAmount = reduceAmount.compareTo(BigDecimal.valueOf(0)) < 0 ? BigDecimal.valueOf(0) : reduceAmount;
				actType = PreferentialModeEnum.SPECIAL_OFFER.getCode();
			}
			if (marketing.getServiceType().equals(MarketingServiceTypeEnum.FREQUENCY.getType())
					|| marketing.getServiceType().equals(MarketingServiceTypeEnum.FREE.getType())) {
				reduceAmount = param.getHairServiceOriginPrice().setScale(2, BigDecimal.ROUND_HALF_UP);
				actType = PreferentialModeEnum.FREE.getCode();
			}
			reduceAmount = reduceAmount.compareTo(param.getHairServiceOriginPrice()) > 0 ? param.getHairServiceOriginPrice() : reduceAmount;
			
			if (isExcludeOnylyMarketing || reduceAmount.compareTo(param.getHairServiceOriginPrice()) >= 0
					|| marketing.getServiceType().equals(MarketingServiceTypeEnum.FIXED.getType())
					|| marketing.getServiceType().equals(MarketingServiceTypeEnum.FREQUENCY.getType())
					|| marketing.getServiceType().equals(MarketingServiceTypeEnum.FREE.getType())) {
				if (data.getMarketingId() == null || data.getMarketingReduceAmount().compareTo(reduceAmount) < 0
						|| (data.getMarketingReduceAmount().compareTo(reduceAmount) == 0
								&& marketing.getUseEndTime().before(data.getMarketingEndTime()))) {
					data.setMarketingId(marketing.getId());
					data.setMarketingType(activityType);
					data.setMarketingReduceAmount(reduceAmount);
					data.setMarketingDiscountType(actType);
					data.setMarketingDenominationAmount(marketing.getCouponAmount());
					data.setMarketingName(marketing.getMarketingName());
					data.setMarketingEndTime(marketing.getUseEndTime());
					data.setMarketingRefundType(marketing.getRefundType());
					data.setMarketingSubsidyType(marketing.getPreferentialUndertakeType());
					data.setMarketingSubsidyBasicAmount(marketing.getHeadquartersPreferentialUndertake());
				}
			} else {
				responseList.add(marketingResponse);
			}
		}
		return responseList;
	}

	private List<BaseActivityResponse> getExcludeOnlyChoiceActivity(ActivityCombinationParam param,
			ActivityCalculation data, List<BaseActivityResponse> availableActivityList) {
		List<BaseActivityResponse> responseList = new ArrayList<BaseActivityResponse>();
		for (BaseActivityResponse activityResponse : availableActivityList) {
			ActivityApiResponseVo activity = (ActivityApiResponseVo) activityResponse;
			BigDecimal reduceAmount = BigDecimal.valueOf(0);
			Integer actType = 0;
			if (activity.getPreferentialMode() == PreferentialModeEnum.REDUCE.getCode()) {
				reduceAmount = activity.getActivityAmount();
				actType = PreferentialModeEnum.REDUCE.getCode();
			}
			if (activity.getPreferentialMode() == PreferentialModeEnum.DISCOUNT.getCode()) {
				reduceAmount = param.getHairServiceOriginPrice()
						.multiply(BigDecimal.valueOf(1).subtract(activity.getActivityAmount()))
						.setScale(2, BigDecimal.ROUND_HALF_UP);
				actType = PreferentialModeEnum.DISCOUNT.getCode();

			}
			if (activity.getPreferentialMode() == PreferentialModeEnum.SPECIAL_OFFER.getCode()) {
				reduceAmount = param.getHairServiceOriginPrice().subtract(activity.getActivityAmount()).setScale(2,
						BigDecimal.ROUND_HALF_UP);
				reduceAmount = reduceAmount.compareTo(BigDecimal.valueOf(0)) < 0 ? BigDecimal.valueOf(0) : reduceAmount;
				actType = PreferentialModeEnum.SPECIAL_OFFER.getCode();
			}
			if (activity.getPreferentialMode() == PreferentialModeEnum.FREE.getCode()) {
				reduceAmount = param.getHairServiceOriginPrice().setScale(2,
						BigDecimal.ROUND_HALF_UP);
				actType = PreferentialModeEnum.FREE.getCode();
			}
			reduceAmount = reduceAmount.compareTo(param.getHairServiceOriginPrice()) > 0 ? param.getHairServiceOriginPrice() : reduceAmount;
			if (activity.getIsOverlying() == Constant.STATUS_NO
					|| reduceAmount.compareTo(param.getHairServiceOriginPrice()) >= 0) {
				if (data.getActivityId() == null 
						|| data.getActivityReduceAmount().compareTo(reduceAmount) < 0
						|| (data.getActivityReduceAmount().compareTo(reduceAmount) == 0
								&& activity.getEndTime().before(data.getActivityEndTime())
								&& !data.getIsBypassFlow())) {
					data.setActivityId(activity.getId());
					data.setActivityDiscountType(actType);
					data.setActivityType(0);
					data.setActivityReduceAmount(reduceAmount);
					data.setActivityDenominationAmount(activity.getActivityAmount());
					data.setActivityName(activity.getName());
					data.setActivityEndTime(activity.getEndTime());
					data.setIsBypassFlow(ActivityTypeEnum.BYPASS_FLOW.getStatusType().equalsIgnoreCase(activity.getActivityType()) ? Boolean.TRUE : Boolean.FALSE);
				}
			} else {
				responseList.add(activityResponse);
			}
		}
		return responseList;
	}

	@Override
	public ResponseMessage getUserActivity(ActivityCombinationParam param) {
		buildUserAllUserIdsAndUserType(param);
		UserActivityResponseVo response = new UserActivityResponseVo();
		userActivityService.getUserAvailableStoreActivity(param, response);
		return ResponseMessage.ok(response);
	}

	private void buildUserAllUserIdsAndUserType(ActivityCombinationParam param) {
		buildUserAllUserIds(param);
		if(param.getUserType()==null){
			Integer userType = userService.verifyIsNewUser(param.getUserId());
			param.setUserType(userType);
		}
	}

	@Override
	public ResponseMessage getUserCoupon(ActivityCombinationParam param) {
		buildUserAllUserIds(param);
		UserActivityResponseVo response = new UserActivityResponseVo();
		userActivityService.getUserAvailableCouponActivity(param, response);
		return ResponseMessage.ok(response);
	}

	@Override
	public ResponseMessage getUserCard(ActivityCombinationParam param) {
		buildUserAllUserIds(param);
		UserActivityResponseVo response = new UserActivityResponseVo();
		userActivityService.getUserAvailableCardActivity(param, response);
		return ResponseMessage.ok(response);
	}

	private void buildUserAllUserIds(ActivityCombinationParam param) {
		if (CollectionUtils.isEmpty(param.getUserIds())) {
			List<Long> userList = userService.queryUserIdsByUserId(param.getUserId());
			param.setUserIds(userList);
		}
	}

	@Override
	public ResponseMessage checkUserActivity(ActivityUseParam param) {
		ActivityCalculation combinationData = new ActivityCalculation();
		TMarketingReceiveHistory history = null;
		TActivity activity = null;
		if (param.getActivityId() == null) {
			history = selectMarketingReceiveHistoryByPrimaryKey(param.getMarketingReceiveHistoryId(),param.getMarketingType());
			if(history ==null) {
				return ResponseMessage.ok(combinationData);
			}
			MarketingReceiveHistoryResponseVo responseVo = userActivityService.buildNewMarketingResponse(history, param.getStoreId(), param.getHairServiceId(), param.getHairServiceOriginPrice(), new Date());
			if (responseVo.getIsAvailable() == Constant.STATUS_NO) {
				return ResponseMessage.error(responseVo.getUnusableReason(),500);
			}
			buildMarketingCombinationData(param.getHairServiceOriginPrice(), combinationData, responseVo);
			return ResponseMessage.ok(combinationData);
		}
		if (param.getMarketingReceiveHistoryId() == null) {
			activity = tActivityMapper.selectByPrimaryKey(param.getActivityId());
			if(activity ==null) {
				return ResponseMessage.ok(combinationData);
			}
			//Integer userType = buildUserType(param.getUserId(),param.getStoreId());
			Integer userType = userService.verifyIsNewUser(param.getUserId());
			ActivityApiResponseVo responseVo = userActivityService.buildNewActivityResponse(activity, param.getStoreId(), param.getUserId(), userType, param.getHairServiceId(), param.getHairServiceOriginPrice(), param.getAppointmentDate());
			if (responseVo.getIsAvailable() == Constant.STATUS_NO) {
				return ResponseMessage.error(responseVo.getUnusableReason(),500);
			}
			buildActivityCombinationData(param.getHairServiceOriginPrice(), combinationData, activity);
			return ResponseMessage.ok(combinationData);
		}
		history = selectMarketingReceiveHistoryByPrimaryKey(param.getMarketingReceiveHistoryId(),param.getMarketingType());
		activity = tActivityMapper.selectByPrimaryKey(param.getActivityId());
		Boolean isCompatible = Boolean.TRUE;
		PreferentialModeEnum preferentialModeEnum = PreferentialModeEnum.parseStatus(activity.getPreferentialMode());
		switch (preferentialModeEnum) {
		case SPECIAL_OFFER:
			isCompatible = Boolean.FALSE;
			break;
		case FREE:
			isCompatible = Boolean.FALSE;
			break;
		case REDUCE:
			if (activity.getIsOverlying() == Constant.STATUS_NO) {
				isCompatible = Boolean.FALSE;
			}
			if ((!history.getServiceType().equals(MarketingServiceTypeEnum.DISCOUNT.getType()))
					&& (!history.getServiceType().equals(MarketingServiceTypeEnum.CASH.getType()))) {
				isCompatible = Boolean.FALSE;
			}
			break;
		case DISCOUNT:
			if (activity.getIsOverlying() == Constant.STATUS_NO) {
				isCompatible = Boolean.FALSE;
			}
			if ((!history.getServiceType().equals(MarketingServiceTypeEnum.DISCOUNT.getType()))
					&& (!history.getServiceType().equals(MarketingServiceTypeEnum.CASH.getType()))) {
				isCompatible = Boolean.FALSE;
			}
			break;
		default:
			isCompatible = Boolean.FALSE;
			break;
		}
		if (isCompatible) {
			//Integer userType = buildUserType(param.getUserId(),param.getStoreId());
			Integer userType = userService.verifyIsNewUser(param.getUserId());
			ActivityApiResponseVo activityResponseVo = userActivityService.buildNewActivityResponse(activity, param.getStoreId(), param.getUserId(), userType, param.getHairServiceId(), param.getHairServiceOriginPrice(), param.getAppointmentDate());
			if (activityResponseVo.getIsAvailable() == Constant.STATUS_NO) {
				return ResponseMessage.error(activityResponseVo.getUnusableReason(),500);
			}
			MarketingReceiveHistoryResponseVo responseVo = userActivityService.buildNewMarketingResponse(history, param.getStoreId(), param.getHairServiceId(), param.getHairServiceOriginPrice(), new Date());
			if (responseVo.getIsAvailable() == Constant.STATUS_NO) {
				return ResponseMessage.error(responseVo.getUnusableReason(),500);
			}
			buildActivityCombinationData(param.getHairServiceOriginPrice(), combinationData, activity);
			buildMarketingCombinationData(param.getHairServiceOriginPrice(), combinationData, responseVo);
			return ResponseMessage.ok(combinationData);
		}
		if (param.getPreferentialType() == 0) { // 点击行为为活动
			//Integer userType = buildUserType(param.getUserId(),param.getStoreId());
			Integer userType = userService.verifyIsNewUser(param.getUserId());
			ActivityApiResponseVo responseVo = userActivityService.buildNewActivityResponse(activity, param.getStoreId(), param.getUserId(), userType, param.getHairServiceId(), param.getHairServiceOriginPrice(), param.getAppointmentDate());
			if (responseVo.getIsAvailable() == Constant.STATUS_NO) {
				return ResponseMessage.error(responseVo.getUnusableReason(),500);
			}
			buildActivityCombinationData(param.getHairServiceOriginPrice(), combinationData, activity);
			return ResponseMessage.ok(combinationData);
		} else {// 点击行为为用户券，卡
			MarketingReceiveHistoryResponseVo responseVo = userActivityService.buildNewMarketingResponse(history, param.getStoreId(), param.getHairServiceId(), param.getHairServiceOriginPrice(), new Date());
			if (responseVo.getIsAvailable() == Constant.STATUS_NO) {
				return ResponseMessage.error(responseVo.getUnusableReason(),500);
			}
			buildMarketingCombinationData(param.getHairServiceOriginPrice(), combinationData, responseVo);
			return ResponseMessage.ok(combinationData);
		}
	}

	private void buildActivityCombinationData(BigDecimal price, ActivityCalculation combinationData,
			TActivity activity) {
		BigDecimal reduceAmount = BigDecimal.valueOf(0);
		Integer actType = 0;
		if (activity.getPreferentialMode() == PreferentialModeEnum.REDUCE.getCode()) {
			reduceAmount = activity.getActivityAmount();
			actType = PreferentialModeEnum.REDUCE.getCode();
		}
		if (activity.getPreferentialMode() == PreferentialModeEnum.DISCOUNT.getCode()) {
			reduceAmount = price.multiply(BigDecimal.valueOf(1).subtract(activity.getActivityAmount())).setScale(2,
					BigDecimal.ROUND_HALF_UP);
			actType = PreferentialModeEnum.DISCOUNT.getCode();

		}
		if (activity.getPreferentialMode() == PreferentialModeEnum.SPECIAL_OFFER.getCode()) {
			reduceAmount = price.subtract(activity.getActivityAmount()).setScale(2, BigDecimal.ROUND_HALF_UP);
			actType = PreferentialModeEnum.SPECIAL_OFFER.getCode();
		}
		if (activity.getPreferentialMode() == PreferentialModeEnum.FREE.getCode()) {
			reduceAmount = price.setScale(2, BigDecimal.ROUND_HALF_UP);
			actType = PreferentialModeEnum.FREE.getCode();
		}
		combinationData.setActivityId(activity.getId());
		combinationData.setActivityDiscountType(actType);
		combinationData.setActivityType(0);
		combinationData.setActivityReduceAmount(reduceAmount);
		combinationData.setActivityDenominationAmount(activity.getActivityAmount());
		combinationData.setActivityName(activity.getName());
		combinationData.setActivityEndTime(activity.getEndTime());
		combinationData.setIsBypassFlow(ActivityTypeEnum.BYPASS_FLOW.getStatusType().equalsIgnoreCase(activity.getActivityType()));
	}

	private void buildMarketingCombinationData(BigDecimal price, ActivityCalculation combinationData,
			MarketingReceiveHistoryResponseVo history) {
		BigDecimal reduceAmount = BigDecimal.valueOf(0);
		Integer actType = 0;
		if (history.getServiceType().equals(MarketingServiceTypeEnum.DISCOUNT.getType())) {
			reduceAmount = price.multiply(BigDecimal.valueOf(1).subtract(history.getCouponAmount())).setScale(2,
					BigDecimal.ROUND_HALF_UP);
			actType = PreferentialModeEnum.DISCOUNT.getCode();
		}
		if (history.getServiceType().equals(MarketingServiceTypeEnum.CASH.getType())) {
			reduceAmount = history.getCouponAmount();
			actType = PreferentialModeEnum.REDUCE.getCode();
		}
		if (history.getServiceType().equals(MarketingServiceTypeEnum.FIXED.getType())) {
			reduceAmount = price.subtract(history.getCouponAmount()).setScale(2, BigDecimal.ROUND_HALF_UP);
			actType = PreferentialModeEnum.SPECIAL_OFFER.getCode();
		}
		if (history.getServiceType().equals(MarketingServiceTypeEnum.FREQUENCY.getType())
				|| history.getServiceType().equals(MarketingServiceTypeEnum.FREE.getType())) {
			reduceAmount = price.setScale(2, BigDecimal.ROUND_HALF_UP);
			actType = PreferentialModeEnum.FREE.getCode();
		}
		combinationData.setMarketingId(history.getId());
		combinationData.setMarketingType((MarketingTypeEnum.parseStatus(history.getMarketingType()).getOrderCode()));
		combinationData.setMarketingReduceAmount(reduceAmount);
		combinationData.setMarketingDiscountType(actType);
		combinationData.setMarketingDenominationAmount(history.getCouponAmount());
		combinationData.setMarketingName(history.getMarketingName());
		combinationData.setMarketingEndTime(history.getUseEndTime());
		combinationData.setMarketingRefundType(history.getRefundType());
		combinationData.setMarketingSubsidyType(history.getPreferentialUndertakeType());
		combinationData.setMarketingSubsidyBasicAmount(history.getHeadquartersPreferentialUndertake());
	}

	@Override
	public ResponseMessage getStoreBypassFlowActivityList(ActivityCombinationParam param) {
		ActivityCalculation data = new ActivityCalculation();
		buildUserAllUserIdsAndUserType(param);
		UserActivityResponseVo response = new UserActivityResponseVo();
		userActivityService.getUserAvailableStoreBypassFlowActivity(param, response);
		if (!CollectionUtils.isEmpty(response.getAvailableActivityList())) {
			ActivityApiResponseVo activity = (ActivityApiResponseVo) response.getAvailableActivityList().get(0);
			BigDecimal reduceAmount = BigDecimal.valueOf(0);
			Integer actType = 0;
			if (activity.getPreferentialMode() == PreferentialModeEnum.REDUCE.getCode()) {
				reduceAmount = activity.getActivityAmount();
				actType = PreferentialModeEnum.REDUCE.getCode();
			}
			if (activity.getPreferentialMode() == PreferentialModeEnum.DISCOUNT.getCode()) {
				reduceAmount = param.getHairServiceOriginPrice()
						.multiply(BigDecimal.valueOf(1).subtract(activity.getActivityAmount()))
						.setScale(2, BigDecimal.ROUND_HALF_UP);
				actType = PreferentialModeEnum.DISCOUNT.getCode();

			}
			if (activity.getPreferentialMode() == PreferentialModeEnum.SPECIAL_OFFER.getCode()) {
				reduceAmount = param.getHairServiceOriginPrice().subtract(activity.getActivityAmount()).setScale(2,
						BigDecimal.ROUND_HALF_UP);
				actType = PreferentialModeEnum.SPECIAL_OFFER.getCode();
			}
			if (activity.getPreferentialMode() == PreferentialModeEnum.FREE.getCode()) {
				reduceAmount = param.getHairServiceOriginPrice().setScale(2,
						BigDecimal.ROUND_HALF_UP);
				actType = PreferentialModeEnum.FREE.getCode();
			}
			data.setActivityId(activity.getId());
			data.setActivityDiscountType(actType);
			data.setActivityType(0);
			data.setActivityReduceAmount(reduceAmount);
			data.setActivityDenominationAmount(activity.getActivityAmount());
			data.setActivityName(activity.getName());
			data.setActivityEndTime(activity.getEndTime());
		}
		return ResponseMessage.ok(data);
	}

	@Override
	public ResponseMessage getStoreBypassFlowActivityTime(Long storeId,Long hairdresserId,Long hairServiceId, String startDate, String endDate) {
		Date sDate = DateUtils.parseDate(startDate);
		Date eDate = DateUtils.parseDate(endDate);
		eDate = DateUtils.getCurdate(eDate);
		eDate = DateUtils.parseDate(DateUtils.formatDate(eDate, DateUtils.DATE_FORMAT_EN)+"235959");
		Map responseMap = userActivityService.getStoreAvailableStoreBypassFlowActivity(storeId,hairdresserId,hairServiceId, sDate, eDate);
		return ResponseMessage.ok(responseMap);
	}

	@Override
	public ResponseMessage getUserCardAuthInfo(Long userId) {
		//判定用户是否有未激活的卡
		TMarketingReceiveHistoryCardExample cardExample = new TMarketingReceiveHistoryCardExample();
		cardExample.createCriteria()
							  		   .andUserIdEqualTo(userId)
							  		   .andStatusEqualTo(Constant.STATUS_YES)
							  		   .andMarketingTypeEqualTo(MarketingTypeEnum.CARD.getCode())
							  		   .andServiceTypeEqualTo(MarketingServiceTypeEnum.FREE.getType())
							  		   .andAuthStatusEqualTo(Constant.STATUS_NO);
		int cardCount =tMarketingReceiveHistoryCardMapper.countByExample(cardExample);
		//判定用户是否有快到期的券
		TMarketingReceiveHistoryCouponExample couponExample = new TMarketingReceiveHistoryCouponExample();
		couponExample.createCriteria()
							  		   .andUserIdEqualTo(userId)
							  		   .andStatusEqualTo(Constant.STATUS_YES)
							  		   .andMarketingTypeEqualTo(MarketingTypeEnum.COUPON.getCode())
							  		   .andUseEndTimeLessThanOrEqualTo(DateUtils.addSomeDays(new Date(), 14))
							  		   .andUseStartTimeLessThanOrEqualTo(new Date());
		int couponCount =tMarketingReceiveHistoryCouponMapper.countByExample(couponExample);
		JSONObject json =new JSONObject();
		json.put("cardCount", cardCount);
		json.put("couponCount", couponCount);
		return ResponseMessage.ok(json);
	}
	
	private TMarketingReceiveHistory selectMarketingReceiveHistoryByPrimaryKey(Long marketingReceiveHistoryId,
			Integer marketingType) {
		if (marketingType.intValue() == MarketingTypeEnum.COUPON.getCode()) {
			return tMarketingReceiveHistoryCouponMapper.selectByPrimaryKey(marketingReceiveHistoryId);
		} else if (marketingType.intValue() == MarketingTypeEnum.CARD.getCode()) {
			return tMarketingReceiveHistoryCardMapper.selectByPrimaryKey(marketingReceiveHistoryId);
		} else if (marketingType.intValue() == MarketingTypeEnum.COUPON_BAG.getCode()) {
			return tMarketingReceiveHistoryCouponBagMapper.selectByPrimaryKey(marketingReceiveHistoryId);
		}
		return null;
	}

	@Override
	public ResponseMessage checkUserHasMarketingAndActivty(ActivityCombinationParam param) {
		// 查询用户所有权益-含用户所有可用券，卡，及当前门店活动
		UserActivityResponseVo response = getUserAllAvailableActivity(param);
		Boolean hasMarketing = (CollectionUtils.isEmpty(response.getAvailableCouponList()) && CollectionUtils.isEmpty(response.getAvailableCardList())) ? Boolean.FALSE: Boolean.TRUE;
		Boolean hasActivity = CollectionUtils.isEmpty(response.getAvailableActivityList()) ? Boolean.FALSE: Boolean.TRUE;
		Map hasResult = new HashMap();
		hasResult.put("hasMarketing", hasMarketing);
		hasResult.put("hasActivity", hasActivity);
		return ResponseMessage.ok(hasResult);
	}
}
